package com.pactera.jep.service.sys.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.pactera.jep.sys.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.pactera.jep.commons.CollectionUtils;
import com.pactera.jep.commons.DateUtils;
import com.pactera.jep.core.code.PermitType;
import com.pactera.jep.core.security.token.Token;
import com.pactera.jep.core.security.token.TokenService;
import com.pactera.jep.core.security.token.impl.TokenBuilder;
import com.pactera.jep.service.sys.security.spring.bean.UserEntity;
import com.pactera.jep.service.sys.util.UserNameCache;
import com.pactera.jep.sys.code.ResourceKind;
import com.pactera.jep.sys.model.Authorization;
import com.pactera.jep.sys.model.Staff;
import com.pactera.jep.sys.model.User;
import com.pactera.jep.web.entity.UserAuthorization;

/**
 * 从数据源处根据username加载对应的用户数据
 *
 * @author ghost
 */
@Component
public class SecurityService implements UserDetailsService {

    private final static Logger logger = LoggerFactory.getLogger(SecurityService.class);

    @Autowired
    private UserService userService;

    @Autowired
    private StaffService staffService;

    @Autowired
    private AuthorizationService authorizationService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private UserNameCache userNameCache;

    @Autowired
    private RoleService roleService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (!StringUtils.hasLength(username)) {
            logger.error("传入的用户名为空！");
            throw new UsernameNotFoundException("传入的用户名为空！");
        }
        return loadUserDetail(username);
    }

    /**
     * 根据用户名查询用户相关数据以及用户相关权限数据
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    private UserDetails loadUserDetail(String username) throws UsernameNotFoundException {
        String system = "";
        if (username.contains("#")) {
            String[] name = username.split("#");
            system = name[0];
            username = name[1];
        }

        if (StringUtils.isEmpty(username)) {
            logger.error("传入的用户名为空!");
            throw new UsernameNotFoundException("传入的用户名为空！");
        }
        // 首先通过UserService查询出用户基础数据
        User user = userService.get(username);
        if (user == null) {
            logger.error("没有找到用户名为{}的用户数据。", username);
            throw new UsernameNotFoundException("用户不存在!");
        }
        // 如果用户存在，那么从staffService中查询出用户角色
        Staff staff = staffService.get(username);
        if (staff == null) {
            logger.error("没有查询到用户名为{}的角色数据。", username);
            throw new UsernameNotFoundException("没有查询到用户" + username + "的角色!");
        }
        // 将用户的staffCode保存进UserNameCache中
        userNameCache.setName(staff.getStaffCode());
        userNameCache.setSystem(system);
        // 获取数据权限
        List<Authorization> authorizations = authorizationService
                .selectPermitAuthorization4StaffCode(staff.getStaffCode());
        Map<String, List<UserAuthorization>> authMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(authorizations)) {
            for (Authorization auth : authorizations) {
                if (!ResourceKind.PERMIT.name().equals(auth.getKind()))
                    continue;

                UserAuthorization userAuth = new UserAuthorization();
                userAuth.setKind(ResourceKind.PERMIT.name());
                /* 数据权限类型 */
                PermitType type = PermitType.valueOf(auth.getResourceCode());
                userAuth.setResourceCode(type.name());
                userAuth.setResourceData(type.getWeight());

                String menuCode = auth.getMenuCode();
                List<UserAuthorization> list = authMap.get(menuCode);
                if (list == null) {
                    list = new ArrayList<>();
                    authMap.put(menuCode, list);
                }
                list.add(userAuth);
            }
        }
        String tenantId = staff.getTenantId();

        // 创建token
        TokenBuilder builder = TokenBuilder.newTokenBuilder(user.getUserId(), "login", "login")
                .username(user.getUserName()).property("loginTime", DateUtils.formatDateTime(new Date()))
                .property("unitCode", staff.getUnitCode()).property("unitName", staff.getUnitName())
                .property("deptCode", staff.getDeptCode()).property("deptName", staff.getDeptName())
                .property("tenantId", tenantId).property("authorization", authMap);

        Token loginToken = builder.expirationInMinutes(30).build();
        String newToken = tokenService.encode(loginToken);
        UserEntity userEntity = new UserEntity(user);
        userEntity.setToken(newToken);
        userEntity.setStaff(staff);
        if (StringUtils.hasLength(system)) {
            userEntity.setMenus(menuService.selectMenu(staff.getStaffCode(), system));
        } else {
            userEntity.setMenus(menuService.selectMenuByStaffCode(staff.getStaffCode()));
        }
        userEntity.setRoles(roleService.selectRoleCodeByStaffCode(staff.getStaffCode()));
        return userEntity;
    }
}
